#!/bin/bash

set -eux

PLATFORM_LIST=(Android Linux Windows)
BUILD_TYPE_LIST=(Debug Release RelWithDebInfo MinSizeRel)

function Usage()
{
    echo "Usage: $0 <PLATFORM> <BUILD_TYPE>"
    echo "  PLATFORM: ${PLATFORM_LIST[@]}"
    echo "  BUILD_TYPE: ${BUILD_TYPE_LIST[@]}"
    exit 1
}

function IsSourced()
{
    [ "${FUNCNAME[1]}" = "source" ]
}

# Usage: MatchSimilarWord <WORD> <WORD_LIST>
# Find the most similar word in word list
# Example: MatchSimilarWord f foo bar buz will return foo
#          MatchSimilarWord b foo bar buz will return bar buz
function MatchSimilarWord()
{
    local Pattern=${1,,}
    local Word
    local Match=
    shift
    for Word in $@; do
        if [[ ${Word,,} == ${Pattern} ]]; then
            Match=${Word}
            break
        elif [[ ${Word,,} =~ ^${Pattern}.*$ ]]; then
            if [ -z "${Match}" ]; then
                Match=${Word}
            else
                Match="${Match} ${Word}"
            fi
        fi
    done
    echo "${Match}"
}

function CheckBuildPath()
{
    local TargetName="$1_$2"
    local BuildPath="build"
    local BackupPath="${BuildPath}_${TargetName}"
    local BackupName
    if [ -d "${BuildPath}" ]; then
        if [ -f "${BuildPath}/TargetName" ]; then
            BackupName="`cat ${BuildPath}/TargetName`"
            if [ "x${BackupName}" != "x${TargetName}" ]; then
                mv "${BuildPath}" "${BuildPath}_${BackupName}"
                CheckBuildPath $1 $2
            fi
        else
            rm -rf "${BuildPath}"
            CheckBuildPath $1 $2
        fi
    else
        if [ -d "${BackupPath}" ]; then
            mv "${BackupPath}" "${BuildPath}"
            CheckBuildPath $1 $2
        else
            mkdir -p "${BuildPath}"
            echo "${TargetName}" > "${BuildPath}/TargetName"
        fi
    fi
}

function CheckCMakeVersion()
{
    local Minimum=$1
    local Current=`cmake --version | grep "cmake version" | awk '{print $3}'`
    local Latest=`echo -e "${Minimum}\n${Current}" | sort -rV | head -n 1`
    if [ "x${Latest}" != "x${Current}" ]; then
        return 1
    fi
}

function WaitProcess()
{
    local PID=$1
    while [ -d /proc/${PID} ]; do
        echo -n "."
        sleep 0.5
    done
    echo ""
    wait ${PID}
}

function DownloadLatestFile()
{
    local Directory=$2
    local BaseURL="ftp://127.0.0.1"
    local FileURL="${BaseURL}/$1"
    local Username="root"
    local Password="1234"
    local CURL="curl -s -u ${Username}:${Password}"
    local FileName="${Directory}/`basename $1`"
    local FileTime="19700101 00:00:00"
    local NewFileTime
    if [ -f "${FileName}" ]; then
        FileTime="`stat -c %y ${FileName}|sed 's/-\|\.[0-9]\{9\}//g'`"
    else
        mkdir -p ${Directory}
    fi
    echo "Download file: ${FileName}"
    ${CURL} -z "${FileTime}" "${FileURL}" -o "${FileName}" &
    WaitProcess $!
    if [ $? != 0 ]; then
        echo "error: Download ${FileURL} failed!"
        return 1
    else
        NewFileTime="`stat -c %y ${FileName}|sed 's/-\|\.[0-9]\{9\}//g'`"
        if [ "x${FileTime}" != "x${NewFileTime}" ]; then
            echo "Extract file: ${FileName}"
            unzip -o -q "${FileName}" -d "${Directory}" &
            WaitProcess $!
            if [ $? != 0 ]; then
                echo "error: unzip ${FileName} failed!"
                return 1
            fi
        else
            echo "info: Local file ${FileName} is newer than server."
        fi
    fi
}

function CMakeBuildProject()
{
    local Project=$1
    local Platform=$2
    local BuildType=$3
    local ToolchainFile="`pwd`/cmake/${Platform}.cmake"
    cmake -G "Unix Makefiles" \
        -D "CMAKE_TOOLCHAIN_FILE=${ToolchainFile}" \
        -D "CMAKE_BUILD_TYPE=${BuildType}" \
        -S "${Project}" \
        -B "build"
    if [ $? != 0 ]; then
        echo "error: cmake configure ${Project} failed."
        return 1
    fi
    cmake --build "build"
    if [ $? != 0 ]; then
        echo "error: build ${Project} failed."
        return 1
    fi
    cmake --install "build"
    if [ $? != 0 ]; then
        echo "error: install ${Project} failed."
        return 1
    fi
}

function Main()
{
    local Platform=($(MatchSimilarWord $1 ${PLATFORM_LIST[@]}))
    local BuildType=($(MatchSimilarWord $2 ${BUILD_TYPE_LIST[@]}))
    local Count

    Count=${#Platform[@]}
    if [ ${Count} -lt 1 ]; then
        echo "error: PLATFROM is not support"
        exit 1
    fi
    if [ ${Count} -gt 1 ]; then
        echo "error: PLATFROM is match ${Platform[@]}, choose one."
        exit 1
    fi

    Count=${#BuildType[@]}
    if [ ${Count} -lt 1 ]; then
        echo "error: BUILD_TYPE is not support"
        exit 1
    fi
    if [ ${Count} -gt 1 ]; then
        echo "error: BUILD_TYPE is match ${BuildType[@]}, choose one."
        exit 1
    fi

    CheckBuildPath ${Platform} ${BuildType}
    local Minimum="3.15.0"
    if ! CheckCMakeVersion "${Minimum}"; then
        echo "error: cmake version is too old, minimum version is ${Minimum}"
        exit 1
    fi
    if ! DownloadLatestFile "source/zlib-1.2.12.zip" "3rdparty"; then
        exit 1
    fi
    CMakeBuildProject "3rdparty/zlib-1.2.12" ${Platform} ${BuildType}
}

if ! IsSourced; then
    if [ $# -ne 2 ]; then Usage; fi
    Main "$@"
fi
